home *** CD-ROM | disk | FTP | other *** search
- /* Kevo -- a prototype-based object-oriented language */
- /* (c) Antero Taivalsaari 1991-1993 */
- /* Some parts (c) Antero Taivalsaari 1986-1988 */
- /* image.c: Image file management & decompilation */
-
- #include "global.h"
-
- /*--------------------------------------------------------------------------*/
- /* Image file forward reference resolver operations */
-
- SOLVE* LastRef = NIL;
-
-
- /* initResolver(): initialize the resolver list */
-
- void initResolver()
- {
- LastRef = NIL;
- }
-
-
- /* addForwardRef(): add a new name to resolver list */
-
- void addForwardRef(name, location)
- char* name;
- int* location;
- {
- SOLVE* newRef = (SOLVE*)mymalloc(sizeof(SOLVE));
-
- #ifdef DEBUG
- printf("Adding forward reference: %s\n", name);
- #endif
-
- newRef->name = allocStrCpy(name);
- newRef->loc = location;
- newRef->next = LastRef;
-
- LastRef = newRef;
- }
-
-
- /* resolveRefs(): resolve all the previous references to a name */
-
- int resolveRefs(name, object)
- char* name;
- int object;
- {
- SOLVE* thisRef = LastRef;
- SOLVE* prevRef = NIL;
- SOLVE* tempRef;
- int count = 0;
-
- while(thisRef) {
- if (strcmp(thisRef->name, name) == 0) {
- *thisRef->loc = object;
- count++;
-
- #ifdef DEBUG
- printf("Resolving forward reference: %s\n", name);
- #endif
-
- if (prevRef == NIL) LastRef = thisRef->next;
- else prevRef->next = thisRef->next;
-
- tempRef = thisRef;
- thisRef = thisRef->next;
-
- free(tempRef->name);
- free(tempRef);
- }
- else {
- prevRef = thisRef;
- thisRef = thisRef->next;
- }
- }
- return(count);
- }
-
-
- /* resolvedOk(): Are all the forward references already resolved? */
-
- int resolvedOk()
- {
- if (LastRef == NIL) return(TRUE);
- else {
- SOLVE* thisRef = LastRef;
- SOLVE* tempRef;
-
- while(thisRef) {
- fprintf(stderr, "Unresolved reference '%s'.\n", thisRef->name);
-
- tempRef = thisRef;
- thisRef = thisRef->next;
-
- free(tempRef->name);
- free(tempRef);
- }
-
- LastRef = NIL;
- return(FALSE);
- }
- }
-
-
- /* ---------------------------------------------------------------------------------- */
-
- /* openImage(): open image file */
-
- void openImage(argc, argv)
- int argc;
- char* argv[];
- {
- if (argc > 1 ) {
- if ((imgfile = fopen(argv[1], "r")) == NIL) {
- printf("%s: cannot open image file \"%s\".\n", argv[0], argv[1]);
- exit(1);
- }
- }
- else {
- if ((imgfile = fopen("kevo.img", "r")) == NIL) {
- /* printf("%s: cannot open standard image file \"kevo.img\".\n", argv[0]); */
- printf("Cannot find standard image file 'kevo.img'.\nCannot continue. Exiting.\n");
- exit(1);
- }
-
- }
- }
-
-
- /* readComment: this operation is needed only in 'loadImage()'. */
- /* Its purpose is to read text until we encounter two right parentheses. */
-
- void readComment()
- {
- paren:
- while(fgetc(imgfile) != ')');
- switch(fgetc(imgfile)) {
- case ')': break;
- default : goto paren;
- }
- }
-
-
- /* loadImage(): load an image file to the system */
- /* xxx This code is rather ugly. Rewrite later. */
-
- void loadImage()
- {
- char command[10];
- char name[64];
- char input[64];
- int number;
-
- PAIR* newPair;
-
- PAIR* pair;
- PAIR* prevPair;
-
- OBJECT* object;
- int* store;
-
- while(fscanf(imgfile, "%s", command) != EOF) {
-
- if (strcmp(command, "::") == 0) {
- if (fscanf(imgfile, "%s %ld", name, &number) == EOF) goto corrupt;
-
- /* xxx we shouldn't limit to 'rootContext' only. Change later. */
-
- /* printf("Defining: %s, number: %ld.\n", name, number); */
-
- newPair = addPair(rootContext, allocStrCpy(name), object = createClosure(number));
- (void)resolveRefs(newPair->nfa, (int)newPair->ofa);
- store = (int*)object->mfa;
-
- prevPair = rootContext->firstPair;
-
- for ( ; number; number--) {
- if (fscanf(imgfile, "%s", input) == EOF) goto corrupt;
-
- if (strcmp(input, "^^") == 0) { /* String literal */
- char* ptr;
- char ch;
-
- *store++ = (int)oStrLit;
- ptr = charbuffer; /* use the shared char buffer (global.c) */
- (void)fgetc(imgfile); /* Read the extra blank */
-
- /* Read text until we find two carats */
- carat:
- while((ch = fgetc(imgfile)) != '^') *ptr++ = ch;
- switch(ch = fgetc(imgfile)) {
- case '^': *ptr = 0; break;
- default : ungetc(ch, imgfile); goto carat;
- }
-
- *store++ = (int)allocStrCpy(charbuffer); number--;
- /* printf("^^%s^^ ", charbuffer); */
- prevPair = rootContext->firstPair;
- }
- else { /* Not a string literal */
- if (strcmp(input, "((") == 0) {
- readComment();
- number++;
- /* printf("Comment "); */
- }
- else {
- char* temp;
- char** endPtr = &temp;
- int result = strtol(input, endPtr, 0);
- if (!**endPtr) {
- *store++ = result; /* Number */
- prevPair = rootContext->firstPair;
- /* printf("%ld ", result); */
- }
- else {
- if (pair = findPairInThis(rootContext, input)) {
- *store++ = (int)pair->ofa;
- /* printf("%s ", pair->nfa); */
-
- /* If '(=context)', allocate a context */
- if (pair->ofa == oContext && prevPair->ofa != oLit) {
-
- /* xxx This must changed when image file loading is implemented in full detail */
- fscanf(imgfile, "%s", input); number--;
- if (strcmp(input, "DUMMY") == 0)
- *store++ = (int)dummyContext;
- else *store++ = (int)lowCreateContext();
- }
-
- prevPair = pair;
- }
- else {
- addForwardRef(input, store++); /* Add to unresolved */
- prevPair = rootContext->firstPair;
- /* printf("Unresolved: %s ", input); */
- }
- }
- }
- }
- }
- if (fscanf(imgfile, "%s %lx", command, &number) == EOF) goto corrupt;
- if (strcmp(command, ";;") != 0) goto corrupt;
- newPair->ffa = number;
- /* printf("\nFlag field: %ld\n", number); */
- }
- else { /* Allow comments outside of definitions, too */
- if (strcmp(command, "((") != 0) goto corrupt;
- else readComment();
- }
- }
- if (!resolvedOk()) {
- printf("Unresolved references in image file.\n");
- printf("Cannot continue. Exiting.\n");
- exit(1);
- }
- return;
-
- corrupt:
- printf("Image file structure corrupted near \"%s\".\n", name);
- printf("Cannot continue. Exiting.\n");
- exit(1);
- }
-
-
- /* initVariables(): initialize certain variables defined in image file
- /* so that primitive definitions can execute high-level definitions. */
- /* In particular, we want to invoke the high-level error routine */
- /* from primitives. */
- void initVariables()
- {
- PAIR* pair;
- STORE* store;
-
- pair = findPairInThis(rootContext, "SystemRoot");
- if (pair && pair->ofa && (store = pair->ofa->mfa)) {
- /* 'SystemRoot' should point to 'rootContext'. Therefore, we */
- /* free the automatically (by 'loadImage') allocated context */
- free(store->pfa);
- store->pfa = (int*)rootContext;
-
- /* 'SystemRoot' must be made a full-fledged object */
- /* by storing itself to its clone family (which is still empty) */
- addToList(rootContext->cloneFamily, pair->ofa);
- }
- else goto error;
-
- pair = findPairInThis(rootContext, "Root");
- if (pair && pair->ofa && (store = pair->ofa->mfa)) {
- /* 'Root' should point to 'userContext'. Therefore, we */
- /* free the automatically (by 'loadImage') allocated context */
- free(store->pfa);
- store->pfa = (int*)userContext;
- oUserRoot = pair->ofa;
-
- /* 'Root' must be made a full-fledged object */
- /* by storing itself to its clone family (which is still empty) */
- addToList(userContext->cloneFamily, oUserRoot);
- }
- else goto error;
-
- /* 'Up', 'firstTask, and 'latestTask' must initially point to the '(user)' task data area */
- pair = findPairInThis(rootContext, "(user)");
- if (pair && pair->ofa && pair->ofa->mfa)
- firstTask = latestTask = up = (TASK**)pair->ofa;
- else goto error;
-
- /* 'oBoot' must point to 'boot' */
- pair = findPairInThis(rootContext, "boot");
- if (pair && pair->ofa && pair->ofa->mfa)
- oBoot = pair->ofa;
- else goto error;
-
- /* 'oShell' must point to 'shell' */
- /* This is needed for the debugger */
- pair = findPairInThis(rootContext, "shell");
- if (pair && pair->ofa && pair->ofa->mfa)
- oShell = pair->ofa;
- else goto error;
-
- /* 'oError' must point to vector 'error' */
- pair = findPairInThis(rootContext, "error");
- if (pair && pair->ofa && pair->ofa->mfa)
- oError = pair->ofa;
- else {
- error:
- printf("Certain name(s) could not be found in image file.\n");
- printf("Cannot continue. Exiting.\n");
- exit(1);
- }
- }
-
-
- /* ------------------------------------------------------------------------------- */
- /* Decompilation and image file generation */
-
- /* decompile the definition of an object */
- void decompile(object)
- OBJECT* object;
- {
- OBJECT** addr = (OBJECT**)object->mfa;
- PAIR* thisPair;
- PAIR* prevPair = rootContext->firstPair; /* xxx Whichever pair will do */
- int count = object->sfa;
-
- ownPrintf(":: ");
-
- if (count) { /* Not a primitive */
-
- if (count > 200) {
- ownPrintf("-- This definition is very large: decompiling only first 200 items -- ");
- ownCr();
- count = 200;
- }
-
- for ( ; count > 0; count--, addr++) {
- thisPair = findNameBackward(*addr);
- if (thisPair) {
- if (strcmp(thisPair->nfa, "(\"lit)") == 0) {
- if (strcmp(prevPair->nfa, "(lit)") == 0) ownPrintf("\"lit) ");
- else {
- ownPrintf("^^ %s^^ ", (char*)*++addr);
- count--;
- }
- }
- else ownPrintf("%s ", thisPair->nfa);
-
- prevPair = thisPair;
- }
- else {
- thisPair = findTypeForward(*addr);
- if (thisPair) {
- ownPrintf("%s:", thisPair->nfa);
- ownPrintf("%d ", (int)*addr);
- }
- else ownPrintf("%d ", (int)*addr);
- prevPair = rootContext->firstPair; /* Any pair will do */
- }
- }
- }
- else { /* Is a primitive */
- ownPrintf("(=primitive) %d ", (int)addr);
- }
- ownPrintf(";;");
-
- thisPair = findNameBackward(object);
- if (thisPair && (thisPair->ffa & ImmedFlag)) ownPrintf(" immediate");
- if (thisPair && (thisPair->ffa & HiddenFlag)) ownPrintf(" hidden");
- ownCr();
- }
-
-
- /* generate an image of the whole system to outfile */
- /* (decompile the definitions of all the objects in their definition order) */
- /* xxx this needs to be reimplemented later */
-
- void generateImage()
- {
- /* xxx remove 'rootContext' later */
- PAIR* pair = rootContext->firstPair;
-
- while (pair != NIL) {
- OBJECT* object = pair->ofa;
- OBJECT** addr = (OBJECT**)object->mfa;
- PAIR* thisPair;
- PAIR* prevPair = rootContext->firstPair; /* Any pair is ok */
- int count = object->sfa;
-
- if (count) { /* Not a primitive */
-
- ownPrintf(":: %s ", pair->nfa);
- ownPrintf("%d ", count);
-
- for ( ; count--; addr++) {
- thisPair = findNameForward(*addr);
- if (thisPair) {
- if (strcmp(thisPair->nfa, "(\"lit)") == 0) {
- if (strcmp(prevPair->nfa, "(lit)") == 0)
- ownPrintf("(\"lit) "); /* (lit) ("lit) */
- else {
- ownPrintf("^^ %s^^ ", (char*)*++addr);
- count--;
- }
- }
- else ownPrintf("%s ", thisPair->nfa);
- prevPair = thisPair;
- }
- else {
- ownPrintf("%d ", (int)*addr);
- prevPair = rootContext->firstPair; /* Any pair is ok */
- }
- }
-
- ownPrintf(";;");
-
- thisPair = findNameForward(object);
- if (thisPair) {
- ownPrintf(" %x", thisPair->ffa);
- ownCr();
- }
- }
- pair = pair->sfa;
- }
- }
-
-
-
-
-
-